AWS CloudShellにDuckDBをインストールしてS3にSQLを投げてみた

AWS CloudShellにDuckDBをインストールしてS3にSQLを投げてみた

Clock Icon2024.12.31

本記事では、AWSのマネジメントコンソールに統合されているリージョナルなターミナル環境「AWS CloudShell」を利用し、OLAPが得意なDBMSであるDuckDB経由でS3上のCSVファイルにSQLを投げる方法を紹介します。

ローカル環境にインストールしたり、EC2を立ち上げたりせず、大きすぎないCSV/Parquet/Icebergなファイルに探索的にSQLを実行したいようなケースで有用です。

1. CloudShellとS3の参照可能な権限でAWSコンソールにログイン

今回の動作確認では、AWS CloudShellからS3上のファイルを読み込みます。

CloudShellの操作とS3の参照権限のあるIAMユーザー・ロールで操作対象のAWSアカウントにログインしましょう。

2. CloudShell にアクセスしduckdbをインストール

AWS コンソールのメニューからCloudShellを起動します。

cloudshell-console

2024年12月時点のCPUアーキテクチャーはx86_64です。

$ uname -m
x86_64

DuckDB Installation ページから

  • command line
  • Linux
  • x86_64

に対応するバイナリをダウンロードします。

$ VERSION=1.1.3
$ wget https://github.com/duckdb/duckdb/releases/download/v${VERSION}/duckdb_cli-linux-amd64.zip && unzip duckdb_cli-linux-amd64.zip

$ ls -1
duckdb
duckdb_cli-linux-amd64.zip

$ $ ./duckdb
v1.1.3 19864453f7
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
D select version();
┌─────────────┐
│ "version"() │
│   varchar   │
├─────────────┤
│ v1.1.3      │
└─────────────┘
D

3. S3 にファイルを用意

Vanderbilt大学の生物統計学科でホストされている次のタイタニックのデータセットを取得し、S3にアップロードします。

https://hbiostat.org/data/repo/titanic3.csv

$ head -n 3 titanic3.csv
"pclass","survived","name","sex","age","sibsp","parch","ticket","fare","cabin","embarked","boat","body","home.dest"
1,1,"Allen, Miss. Elisabeth Walton","female",29,0,0,"24160",211.3375,"B5","S","2",,"St Louis, MO"
1,1,"Allison, Master. Hudson Trevor","male",0.92,1,2,"113781",151.5500,"C22 C26","S","11",,"Montreal, PQ / Chesterville, ON"

S3にアップロードしたS3オブジェクトのS3 URIを取得します。

s3://YOUR-BUCKET-NAME/titanic3.csv

CloudShellからこのS3オブジェクトにアクセスできることを確認してください

$ aws s3 ls s3://YOUR-BUCKET-NAME/titanic3.csv
2024-12-29 12:52:50     116752 titanic3.csv

4. DuckDBからS3のCSVファイルにアクセス

DuckDB CLIのデフォルト設定では、S3にアクセスできません。

$ ./duckdb

D select * from read_csv('s3://YOUR-BUCKET/titanic3.csv');
HTTP Error: HTTP GET error on 'https://YOUR-BUCKET.s3.amazonaws.com/titanic3.csv' (HTTP 403)

httpfs エクステンションを有効にし、AWS SDKと同じ仕組みでクレデンシャルを取得する SECRET を定義します。

D INSTALL httpfs;
D LOAD httpfs;

D CREATE SECRET (
      TYPE S3,
      PROVIDER CREDENTIAL_CHAIN
  );
┌─────────┐
│ Success │
│ boolean │
├─────────┤
│ true    │
└─────────┘

永続的なキーを利用する場合は以下のようにSECRETを定義します

CREATE SECRET (
    TYPE S3,
    KEY_ID 'AKIAXXX',
    SECRET 'wJalXXX',
    REGION 'ap-northeast-1'
);

この状態でS3に問い合わせましょう

D select * from read_csv('s3://YOUR-BUCKET-NAME/titanic3.csv') limit 3;
┌────────┬──────────┬──────────────────────┬─────────┬───┬──────────┬─────────┬───────┬──────────────────────┐
│ pclass │ survived │         name         │   sex   │ … │ embarked │  boat   │ body  │      home.dest       │
│ int64  │  int64   │       varchar        │ varchar │   │ varchar  │ varchar │ int64 │       varchar        │
├────────┼──────────┼──────────────────────┼─────────┼───┼──────────┼─────────┼───────┼──────────────────────┤
│      1 │        1 │ Allen, Miss. Elisa…  │ female  │ … │ S        │ 2       │       │ St Louis, MO         │
│      1 │        1 │ Allison, Master. H…  │ male    │ … │ S        │ 11      │       │ Montreal, PQ / Che…  │
│      1 │        0 │ Allison, Miss. Hel…  │ female  │ … │ S        │         │       │ Montreal, PQ / Che…  │
├────────┴──────────┴──────────────────────┴─────────┴───┴──────────┴─────────┴───────┴──────────────────────┤
│ 3 rows                                                                                14 columns (8 shown) │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

D select survived, count(*) from read_csv('s3://YOUR-BUCKET-NAME/titanic3.csv') group by survived order by survived;
┌──────────┬──────────────┐
│ survived │ count_star() │
│  int64   │    int64     │
├──────────┼──────────────┤
│        0 │          809 │
│        1 │          500 │
└──────────┴──────────────┘

同じデータに対して探索的に調べる場合、データを CTAS でメモリ上のテーブルに展開すると良いでしょう。

D CREATE TABLE titanic AS SELECT * FROM read_csv('s3://YOUR-BUCKET-NAME/titanic3.csv') ;

D SHOW titanic;
┌─────────────┬─────────────┬─────────┬─────────┬─────────┬─────────┐
│ column_name │ column_type │  null   │   key   │ default │  extra  │
│   varchar   │   varchar   │ varchar │ varchar │ varchar │ varchar │
├─────────────┼─────────────┼─────────┼─────────┼─────────┼─────────┤
│ pclass      │ BIGINT      │ YES     │         │         │         │
│ survived    │ BIGINT      │ YES     │         │         │         │
│ name        │ VARCHAR     │ YES     │         │         │         │
│ sex         │ VARCHAR     │ YES     │         │         │         │
│ age         │ DOUBLE      │ YES     │         │         │         │
│ sibsp       │ BIGINT      │ YES     │         │         │         │
│ parch       │ BIGINT      │ YES     │         │         │         │
│ ticket      │ VARCHAR     │ YES     │         │         │         │
│ fare        │ DOUBLE      │ YES     │         │         │         │
│ cabin       │ VARCHAR     │ YES     │         │         │         │
│ embarked    │ VARCHAR     │ YES     │         │         │         │
│ boat        │ VARCHAR     │ YES     │         │         │         │
│ body        │ BIGINT      │ YES     │         │         │         │
│ home.dest   │ VARCHAR     │ YES     │         │         │         │
├─────────────┴─────────────┴─────────┴─────────┴─────────┴─────────┤
│ 14 rows                                                 6 columns │
└───────────────────────────────────────────────────────────────────┘

D select pclass, sex, survived, count(*) from titanic group by pclass, sex, survived order by pclass, sex, survived;
┌────────┬─────────┬──────────┬──────────────┐
│ pclass │   sex   │ survived │ count_star() │
│ int64  │ varchar │  int64   │    int64     │
├────────┼─────────┼──────────┼──────────────┤
│      1 │ female  │        0 │            5 │
│      1 │ female  │        1 │          139 │
│      1 │ male    │        0 │          118 │
│      1 │ male    │        1 │           61 │
│      2 │ female  │        0 │           12 │
│      2 │ female  │        1 │           94 │
│      2 │ male    │        0 │          146 │
│      2 │ male    │        1 │           25 │
│      3 │ female  │        0 │          110 │
│      3 │ female  │        1 │          106 │
│      3 │ male    │        0 │          418 │
│      3 │ male    │        1 │           75 │
├────────┴─────────┴──────────┴──────────────┤
│ 12 rows                          4 columns │
└────────────────────────────────────────────┘

参考

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.